#include <wx/wxprec.h>

#ifdef __BORLANDC__
	#pragma hdrstop
#endif

#ifndef WX_PRECOMP
	#include <wx/wx.h>
#endif
#include <wx/aboutdlg.h>
#include <wx/file.h>
#include <wx/filename.h>
#include <wx/wfstream.h>
#include <wx/datstrm.h>
#include <wx/textfile.h>
#include "myapp.h"
#include "kakeibo.h"

#include "kakeibomeister.xpm"

DECLARE_APP(MyApp);


//---------------------------------------------------------------
// Insert transaction data in list ctrl
//---------------------------------------------------------------
void MyFrame::InsertRow(wxListCtrl *ctrl, wxString list[], size_t size, int imgid[], size_t imgsize)
{
	int index = (ctrl->GetItemCount() == 0) ? 0 : ctrl->GetItemCount();
	
	long tmp = ctrl->InsertItem(index,list[0],-1);
	for (int i = 0; i < 7; i++) {
		wxListItem item;
		item.SetId(tmp);
		item.SetColumn(i);
		item.SetText(list[i]);
		if ((i >= 1) && (i <= 2)) {
			if (imgid[i-1] > -1) {
				ctrl->SetItemColumnImage(tmp,i,imgid[i-1]);
			}
		}
		ctrl->SetItem(item);
	}
	
}
//---------------------------------------------------------------
// Change transaction data of indicated index
//---------------------------------------------------------------
void MyFrame::ChangeRow(wxListCtrl *ctrl, int index, wxString list[], size_t size, int imgid[], size_t imgsize)
{
	wxListItem item;
	item.SetId(index);
	for (int i = 0; i < 7; i++) {
		item.SetColumn(i);
		item.SetText(list[i]);
		if ((i >= 1) && (i <= 2)) {
			if (imgid[i-1] > -1) {
				ctrl->SetItemColumnImage(index,i,imgid[i-1]);
			}
		}
		ctrl->SetItem(item);
	}
}
//---------------------------------------------------------------
// Remove transaction data
//---------------------------------------------------------------
void MyFrame::DeleteRow(wxListCtrl *ctrl, int index)
{
	ctrl->DeleteItem(index);
}
//---------------------------------------------------------------
// Update kakeibo-DB from inputting transaction data
//---------------------------------------------------------------
void MyFrame::UpdateDB(void)
{
	if (!wxGetApp().SQLDB().IsOpen()) return;
	std::vector<DB_day>::iterator it;
	for (it = dbbudget.begin(); it != dbbudget.end(); it++) {
		wxString sql;
		//---add
		if ((*it).GetFlag() == add_mt) {
			//update db_budget
			wxGetApp().AppDB.AddBudget((*it));
			//count up
			wxGetApp().AppDB.CountBudget++;
			wxGetApp().SQLDB().ExecuteUpdate(wxString::Format(_T("update db_counter set ct_budget = %d"),wxGetApp().AppDB.CountBudget));
			//update db_total
			DB_total tdb;
			int tmpremainder = 0, tmpincome = 0, tmpexpenditure = 0;
			tdb.SetDate((*it).GetDate());
			tdb.SetHandling((*it).GetHandling());
			if (wxGetApp().AppDB.GetTotalCount(tdb) == 0) {
				//get early date than input date
				sql = StrF(_T("select tot_remainder, tot_income, tot_expenditure from db_total where tot_date < '%s' and tot_handle = %d order by tot_date desc limit 1;"),
					(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetHandling());
				wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
				while (rset.NextRow()) {
					tmpremainder = rset.GetInt(0);
					//tmpincome = rset.GetInt(1);
					//tmpexpenditure = rset.GetInt(2);
					break;
				}
				tmpremainder += (*it).GetIncome();
				tmpremainder -= (*it).GetExpenditure();
				tmpincome += (*it).GetIncome();
				tmpexpenditure += (*it).GetExpenditure();
				sql = StrF(_T("insert into db_total values ( '%s', %d, %d, %d, %d );"),
					(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetHandling(),tmpincome,
					tmpexpenditure,tmpremainder);
				//count up
				wxGetApp().AppDB.CountTotal++;
				wxGetApp().SQLDB().ExecuteUpdate(wxString::Format(_T("update db_counter set ct_total = %d"),wxGetApp().AppDB.CountTotal));
			}else{
				//get date equal to input date
				sql = StrF(_T("select tot_remainder, tot_income, tot_expenditure from db_total where tot_date = '%s' and tot_handle = %d;"),
					(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetHandling());
				wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
				while (rset.NextRow()) {
					tmpremainder = rset.GetInt(0);
					tmpincome = rset.GetInt(1);
					tmpexpenditure = rset.GetInt(2);
					break;
				}
				tmpremainder += (*it).GetIncome();
				tmpremainder -= (*it).GetExpenditure();
				tmpincome += (*it).GetIncome();
				tmpexpenditure += (*it).GetExpenditure();
				sql = StrF(_T("update db_total set tot_income = %d, tot_expenditure = %d, tot_remainder = %d where tot_date = '%s' and tot_handle = %d;"),
					tmpincome,tmpexpenditure,tmpremainder,(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetHandling());
			}
			//update same date with db_budget
			tdb.SetIncome(tmpincome);
			tdb.SetExpenditure(tmpexpenditure);
			tdb.SetRemainder(tmpremainder);
			//finalize input date and futures dates
			wxGetApp().SQLDB().ExecuteUpdate(sql);
			UpdateFuture(tdb);
			(*it).SetFlag(none_mt);
		}
		//---mod
		if ((*it).GetFlag() == mod_mt) {
			DB_day ddb;
			//get old data
			wxString sql = StrF(_T("select bg_date, bg_income, bg_expenditure from db_budgets where bg_date = '%s' and bg_io = %d and bg_id = %d and bg_handle = %d;"),
				(*it).GetOldDate().Format(DATEFORM).c_str(),(int)((*it).GetIO()),(*it).GetId(),(*it).GetHandling());
			wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
			while (rset.NextRow()) {
				ddb.SetDate(rset.GetDate(0));
				ddb.SetIncome(rset.GetInt(1));
				ddb.SetExpenditure(rset.GetInt(2));
				break;
			}
			//update db_budget
			wxGetApp().AppDB.SetBudget((*it),(*it));
			//update db_total
			DB_total tdb;
			int tmpremainder = 0, tmpincome = 0, tmpexpenditure = 0;
			tdb.SetDate((*it).GetDate());
			tdb.SetHandling((*it).GetHandling());
			int newdatecnt = wxGetApp().AppDB.GetTotalCount(tdb);
			//if date is changed and the date is not exist, it re-append as changed data
			if (newdatecnt == 0) {
				DB_total tdb2 = wxGetApp().AppDB.GetTotalNear(tdb,_T("<"));
				tdb.SetIncome((*it).GetIncome());
				tdb.SetExpenditure((*it).GetExpenditure());
				tdb.SetRemainder(tdb2.GetRemainder()+ddb.GetIncome()-ddb.GetExpenditure());
				wxGetApp().AppDB.AddTotal(tdb);
			}else{
				//if it exists and 2 date is different only, modify new date's
				if (!(*it).GetDate().IsEqualTo((*it).GetOldDate())) {
					DB_total tdb2 = wxGetApp().AppDB.GetTotalNear(tdb,_T("<="));
					tdb2.SetIncome(tdb2.GetIncome()+(*it).GetIncome());
					tdb2.SetExpenditure(tdb2.GetExpenditure()+(*it).GetExpenditure());
					tdb2.SetRemainder(tdb2.GetRemainder()+(*it).GetIncome()-(*it).GetExpenditure());
					wxGetApp().AppDB.SetTotal(tdb2,tdb2);
				}
			}
			//modify data of old date or unchanged date.
			sql = StrF(_T("select tot_remainder, tot_income, tot_expenditure from db_total where tot_date = '%s' and tot_handle = %d;"),
				(*it).GetOldDate().Format(DATEFORM).c_str(),(*it).GetHandling());
			rset = wxGetApp().SQLDB().ExecuteQuery(sql);
			while (rset.NextRow()) {
				tmpremainder = rset.GetInt(0);
				tmpincome = rset.GetInt(1);
				tmpexpenditure = rset.GetInt(2);
				break;
			}
			//subtract old value
			tmpremainder -= ddb.GetIncome();
			tmpremainder += ddb.GetExpenditure();
			tmpincome -= ddb.GetIncome();
			tmpexpenditure -= ddb.GetExpenditure();
			if ((newdatecnt > 0) && ((*it).GetDate().IsEqualTo((*it).GetOldDate()))) {
				//add new value
				tmpremainder += (*it).GetIncome();
				tmpremainder -= (*it).GetExpenditure();
				tmpincome += (*it).GetIncome();
				tmpexpenditure += (*it).GetExpenditure();
			}
			//update same date with db_budget
			tdb.SetDate((*it).GetOldDate());
			tdb.SetIncome(tmpincome);
			tdb.SetExpenditure(tmpexpenditure);
			tdb.SetRemainder(tmpremainder);
			//finalize input date and futures dates
			wxGetApp().AppDB.SetTotal(tdb,tdb);
			UpdateFuture(tdb);
			//if it changed passed date, change together all futures.
			if ((*it).GetDate().IsEarlierThan((*it).GetOldDate())) {
				DB_total cond;
				cond.SetDate((*it).GetDate());
				cond.SetHandling((*it).GetHandling());
				tdb = wxGetApp().AppDB.GetTotal(cond);
				UpdateFuture(tdb);
			}
			(*it).SetFlag(none_mt);
		}
		//---del
		if ((*it).GetFlag() == del_mt) {
			//update db_budget
			wxString sql = wxString::Format(_T("delete from db_budgets where bg_date = '%s' and bg_id = %d and bg_io = %d and bg_handle = %d;"),
				(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetId(),(int)((*it).GetIO()),(*it).GetHandling());
			wxGetApp().SQLDB().ExecuteUpdate(sql);
			//count down
			wxGetApp().AppDB.CountBudget--;
			wxGetApp().SQLDB().ExecuteUpdate(wxString::Format(_T("update db_counter set ct_budget = %d"),wxGetApp().AppDB.CountBudget));
			//update db_total
			DB_total tdb;
			int tmpremainder = 0, tmpincome = 0, tmpexpenditure = 0;
			tdb.SetDate((*it).GetDate());
			tdb.SetHandling((*it).GetHandling());
			sql = StrF(_T("select tot_remainder, tot_income, tot_expenditure from db_total where tot_date = '%s' and tot_handle = %d;"),
				(*it).GetDate().Format(DATEFORM).c_str(),(*it).GetHandling());
			wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
			while (rset.NextRow()) {
				tmpremainder = rset.GetInt(0);
				tmpincome = rset.GetInt(1);
				tmpexpenditure = rset.GetInt(2);
				break;
			}
			tmpremainder -= (*it).GetIncome();
			tmpremainder += (*it).GetExpenditure();
			tmpincome -= (*it).GetIncome();
			tmpexpenditure -= (*it).GetExpenditure();
			
			tdb.SetIncome(tmpincome);
			tdb.SetExpenditure(tmpexpenditure);
			tdb.SetRemainder(tmpremainder);
			rset = wxGetApp().SQLDB().ExecuteQuery(_T("select cf_value from db_config where cf_name = 'cf_startdate';"));
			wxDateTime startdate;
			while (rset.NextRow()) startdate = rset.GetDate(0);
			//finalize input date and futures dates
			if ((tmpincome == 0) && (tmpexpenditure == 0) && (!tdb.GetDate().IsEqualTo(startdate))) {
				sql = StrF(_T("delete from db_total where tot_date = '%s' and tot_handle = %d;"),
					tdb.GetDate().Format(DATEFORM).c_str(),tdb.GetHandling());
				wxGetApp().SQLDB().ExecuteUpdate(sql);
				//count down
				wxGetApp().AppDB.CountTotal--;
				wxGetApp().SQLDB().ExecuteUpdate(wxString::Format(_T("update db_counter set ct_total = %d"),wxGetApp().AppDB.CountTotal));
			}else{
				wxGetApp().AppDB.SetTotal(tdb,tdb);
			}
			UpdateFuture(tdb);
			
		}
	}
	wxGetApp().SetChangeFlag(true);
}
//---------------------------------------------------------------
// Update future data when changed past data
//---------------------------------------------------------------
void MyFrame::UpdateFuture(DB_total &tdb)
{
	wxString sql = StrF(_T("select count(*) from db_total where tot_date > '%s' and tot_handle = %d;"),
		tdb.GetDate().Format(DATEFORM).c_str(),tdb.GetHandling());

	int futcnt = wxGetApp().SQLDB().ExecuteScalar(sql);
	if (futcnt > 0) {
		vector <DB_total> dbs;
		dbs.push_back(tdb);
		//get future date than input date
		sql = StrF(_T("select * from db_total where tot_date > '%s' and tot_handle = %d order by tot_date;"),
			tdb.GetDate().Format(DATEFORM).c_str(),tdb.GetHandling());
		wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
		while (rset.NextRow()) {
			DB_total db;
			db.SetDate(rset.GetDate(0));
			db.SetHandling(rset.GetInt(1));
			db.SetIncome(rset.GetInt(2));
			db.SetExpenditure(rset.GetInt(3));
			db.SetRemainder(rset.GetInt(4));
			dbs.push_back(db);
		}
		//start re-calculate db_total
		for (int i = 1; i < (int)dbs.size(); i++) {
			dbs.at(i).SetRemainder(dbs.at(i-1).GetRemainder() +
				dbs.at(i).GetIncome() - dbs.at(i).GetExpenditure());
			wxGetApp().AppDB.SetTotal(dbs.at(i),dbs.at(i));
		}
	}
}
//---------------------------------------------------------------
// Update related other handling data when changed transaction data
//---------------------------------------------------------------
void MyFrame::UpdateLinkedBudget(DB_day &db)
{
	if ((db.GetExpense() != 3) && (db.GetExpense() != 4)) {
		return;
	}
	int accexpense[2];
	wxString sql;
	DB_day revdb;
	//---when flag is modify or delete
	if ((db.GetFlag() == mod_mt) || (db.GetFlag() == del_mt)) {
		int stpos = db.GetExtra().Find(_T("l"));
		int edcnt = db.GetExtra().Mid(stpos).Find(_T(":"));
		wxString flag = db.GetExtra().Mid(stpos,edcnt);
		sql = StrF(_T("select * from db_budgets where bg_handle != %d and bg_extra like '%s';"),
			db.GetHandling(),StrF(_T("%%%s%%"),flag.c_str()).c_str());
		wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
		//dbbudget.clear();
		//db.SetFlag(none_mt);
		//dbbudget.push_back(db);
		//---search linked transaction in other account.
		while (rset.NextRow()) {
			revdb.SetDate(rset.GetDate(0));
			revdb.SetId(rset.GetInt(1));
			revdb.SetIO((InoutType)rset.GetInt(2));
			revdb.SetHandling(rset.GetInt(3));
			revdb.SetExpense(rset.GetInt(4));
			revdb.SetItems(rset.GetInt(5));
			revdb.SetIncome(rset.GetInt(6));
			revdb.SetExpenditure(rset.GetInt(7));
			revdb.SetMemo(rset.GetString(8));
			revdb.SetExtra(rset.GetString(9));
		}
		revdb.SetIncome(db.GetExpenditure());
		revdb.SetExpenditure(db.GetIncome());
		revdb.SetMemo(db.GetMemo());
		revdb.SetFlag(db.GetFlag());
	}
	//---when flag is add
	if (db.GetFlag() == add_mt) {
		{//---get expense with account flag
			sql = _T("select ex_id from db_expense where ex_account = '1' order by ex_id;");
			wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
			int i = 0;
			while (rset.NextRow()) {
				accexpense[i] = rset.GetInt(0);
				i++;
			}
		}
		revdb.SetDate(db.GetDate());
		revdb.SetIO(db.GetIO() == in_it ? out_it : in_it);
		//---reverse expense
		if (db.GetExpense() == accexpense[0]) {
			revdb.SetExpense(accexpense[1]);
		}else{
			revdb.SetExpense(accexpense[0]);
		}
		{
			vector <int> accdb;
			vector <int> itemdb[2];
			//---get items in expense with account flag
			for (int i = 0; i < 2; i++) {
				sql = StrF(_T("select it_id, it_expense from db_items where it_expense = %d order by it_id, it_expense;"),
					i+3);
				wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
				while (rset.NextRow()) {
					itemdb[i].push_back(rset.GetInt(0));
				}
			}
			//---get account
			sql = _T("select ac_id from db_account order by ac_id;");
			wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
			while (rset.NextRow()) {
				accdb.push_back(rset.GetInt(0));
			}
			for (int i = 0; i < (int)accdb.size(); i++) {
				//---hit original db's handling
				if (db.GetHandling() == accdb.at(i)) {
					revdb.SetItems(itemdb[(int)(revdb.GetIO())].at(i));
				}
				//---hit original db's items of expense
				if (db.GetItems() == itemdb[(int)(db.GetIO())].at(i)) {
					revdb.SetHandling(accdb.at(i));
				}
			}
		}
		revdb.SetIncome(db.GetExpenditure());
		revdb.SetExpenditure(db.GetIncome());
		revdb.SetMemo(db.GetMemo());
		revdb.SetExtra(db.GetExtra());
		revdb.SetId(wxGetApp().AppDB.GetLastIdOfBudget(revdb.GetDate(),(int)(revdb.GetIO()),revdb.GetHandling()));
		revdb.SetFlag(db.GetFlag());
		//---get existed state revdb
		sql = StrF(_T("select count(*) from db_budgets where bg_date = '%s' and bg_io = %d and bg_handle = %d and bg_expense = %d and bg_items = %d;"),
			revdb.GetDate().Format(DATEFORM).c_str(),(int)(revdb.GetIO()),revdb.GetHandling(),revdb.GetExpense(),revdb.GetItems());
		int cnt = wxGetApp().SQLDB().ExecuteScalar(sql);
		//get existed id
		if (cnt > 0) {
			sql.Replace(_T("count(*)"),_T("bg_id"),true);
			revdb.SetId(wxGetApp().SQLDB().ExecuteScalar(sql));
		}else{
			if (db.GetFlag() == del_mt) {
				revdb.SetFlag(none_mt);
			}else{
				revdb.SetFlag(add_mt);
			}
		}
	}
	dbbudget.push_back(revdb);
}
//---------------------------------------------------------------
// Change choosed date or handling
//---------------------------------------------------------------
void MyFrame::ChangePage(const wxDateTime &date, int handling)
{
	if (!wxGetApp().SQLDB().IsOpen()) return;
	DB_day db;
	wxString sql;
	sql = StrF(_T("select * from db_budgets where bg_date = '%s' and bg_handle = %d;"),
		date.Format(DATEFORM).c_str(),handling);
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
	dbbudget.clear();
	db.SetFlag(none_mt);
	while (rset.NextRow()) {
		db.SetDate(rset.GetDate(0));
		db.SetId(rset.GetInt(1));
		db.SetIO((InoutType)rset.GetInt(2));
		db.SetHandling(rset.GetInt(3));
		db.SetExpense(rset.GetInt(4));
		db.SetItems(rset.GetInt(5));
		db.SetIncome(rset.GetInt(6));
		db.SetExpenditure(rset.GetInt(7));
		db.SetMemo(rset.GetString(8));
		db.SetExtra(rset.GetString(9));
		dbbudget.push_back(db);
	}
	/*LOG*/wxGetApp().WriteLog(StrF(_("Transaction at %s is %d."),date.Format(DATEFORM).c_str(),dbbudget.size()));
	km_DayDetail->Freeze();
	km_DayDetail->DeleteAllItems();
	int i;
	for (i = 0; i < (int)dbbudget.size(); i++) {
		wxString arr[7];
		int imageid[2];
		arr[0] = dbbudget.at(i).GetDate().Format(DATEFORM);
		arr[1] = wxGetApp().AppDB.GetExpense(dbbudget.at(i).GetExpense(),dbbudget.at(i).GetIO()).GetName();
		imageid[0] = wxGetApp().AppDB.GetExpense(dbbudget.at(i).GetExpense(),dbbudget.at(i).GetIO()).GetImage();
		arr[2] = wxGetApp().AppDB.GetItems(dbbudget.at(i).GetItems(),dbbudget.at(i).GetExpense()).GetName();
		imageid[1] = wxGetApp().AppDB.GetItems(dbbudget.at(i).GetItems(),dbbudget.at(i).GetExpense()).GetImage();
		arr[3] = wxGetApp().AppDB.GetAccount(dbbudget.at(i).GetHandling()).GetName();
		arr[4] = IntToStr(dbbudget.at(i).GetIncome());
		arr[5] = IntToStr(dbbudget.at(i).GetExpenditure());
		arr[6] = dbbudget.at(i).GetMemo();
		InsertRow(km_DayDetail,arr,sizeof(arr),imageid,2);
	}
	km_DayDetail->Thaw();
	//---get day transaction (not balance)
	int budgetvalue = 0;
	int budgetdiff = 0;
	int cnt = wxGetApp().AppDB.AppSetting.GetBudgetCount();
	for (i = 0; i < cnt; i++) {
		int diff;
		if (CheckBudgetDate(date,handling,wxGetApp().AppDB.AppSetting.GetBudget(i),&diff)) {
			budgetvalue = wxGetApp().AppDB.AppSetting.GetBudget(i).GetValue();
			budgetdiff += budgetvalue + diff;
			break;
		}
	}
	//---get total
	DB_total tdb, rettdb;
	tdb.SetDate(date);
	tdb.SetHandling(handling);
	rettdb = wxGetApp().AppDB.GetTotal(tdb);
	if (rettdb.GetIncome() == -1) {
		rettdb = wxGetApp().AppDB.GetTotalNear(tdb);
		rettdb.SetIncome(0);
		rettdb.SetExpenditure(0);
		ChangeRowTotal(rettdb,budgetvalue,budgetdiff);
	}else{
		ChangeRowTotal(wxGetApp().AppDB.GetTotal(tdb),budgetvalue,budgetdiff);
	}
	dbtotal = rettdb;
	//---set holiday
	int month = (int)date.GetMonth();
	cnt = wxGetApp().AppDB.AppSetting.GetHolidayCount();
	for (i = 0; i < cnt; i++) {
		wxDateTime hdate = wxGetApp().AppDB.AppSetting.GetHoliday(i).GetDate();
		if (hdate.GetMonth() == month) {
			km_Calender->SetHoliday(hdate.GetDay());
		}
	}
}
//---------------------------------------------------------------
// Change sum of transaction data of choosed date
//---------------------------------------------------------------
void MyFrame::ChangeRowTotal(DB_total db, int budget, int budgetdiff)
{
	km_DayResult->SetItem(0, 1, IntToStr(db.GetIncome() == -1 ? 0 : db.GetIncome()));
	km_DayResult->SetItem(1, 1, IntToStr(db.GetExpenditure() == -1 ? 0 : db.GetExpenditure()));
	wxListItem item;
	item.SetId(0);
	item.SetColumn(3);
	item.SetText(IntToStr(db.GetRemainder()));
	if (db.GetRemainder() < 0) {
		item.SetTextColour(wxColour(255,0,0));
	}else{
		item.SetTextColour(wxColour(0,0,0));
	}
	km_DayResult->SetItem(item);
	//budget
	item.SetId(0);
	item.SetColumn(5);
	item.SetText(IntToStr(budget));
	km_DayResult->SetItem(item);
	//difference with budget
	item.SetId(1);
	item.SetColumn(5);
	if (budget > 0) {
		//item.SetText(IntToStr(budget - db.GetExpenditure()));
		item.SetText(IntToStr(budgetdiff));
	}else{
		item.SetText(wxEmptyString);
	}
	km_DayResult->SetItem(item);
}
//---------------------------------------------------------------
// Show sumes of eash expenses
//---------------------------------------------------------------
void MyFrame::GenerateExpenseInDetail(bool onname, bool ondata, int handle, int showtype)
{
	if (!wxGetApp().SQLDB().IsOpen()) return;
	int rows = 0, cols = 0;
	km_WeekDetail->Freeze();
	km_MonthDetail->Freeze();
	//---item labels
	if (onname) {
		wxString sql = StrF(_T("%s %s %s"),
			_T("select ex_name, it_name from db_expense "),
			_T("left join db_items on ex_id = it_expense "),
			_T("group by ex_id, it_id order by ex_io ")
			);
		wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
		while (rset.NextRow()) {
			for (cols = 0; cols < 2; cols++) {
				km_WeekDetail->SetCellValue(rows,cols,rset.GetString(cols));
				km_MonthDetail->SetCellValue(rows,cols,rset.GetString(cols));
			}
			rows++;
		}
		rows++;
		//km_WeekDetail->SetCellValue(rows,0,_("Weekly total"));
		//km_MonthDetail->SetCellValue(rows,0,_("Monthly total"));
		rows++;
		wxString label = _("Income total");
		km_WeekDetail->SetCellValue(rows,0,label);
		km_MonthDetail->SetCellValue(rows,0,label);
		rows++;
		label = _("Expenditure total");
		km_WeekDetail->SetCellValue(rows,0,label);
		km_MonthDetail->SetCellValue(rows,0,label);
		rows++;
		label = _("Change of remainder");
		km_WeekDetail->SetCellValue(rows,0,label);
		km_MonthDetail->SetCellValue(rows,0,label);
		rows++;
	}
	rows = 0;
	//---data of each expenses and items
	if (ondata) {
		//weekly
		if (showtype == 1) {
			wxDateTime first = km_Calender->GetDate();
			first.SetToPrevWeekDay(wxDateTime::Sun);
			wxDateTime last = km_Calender->GetDate();
			last.SetToNextWeekDay(wxDateTime::Sat);
			first.Subtract(wxDateSpan(0,0,2,0));
			last.Subtract(wxDateSpan(0,0,2,0));

			for (int i = 0; i < 5; i++) {
				DB_total totdb, restot;
				totdb.SetHandling(handle);
				totdb.SetDate(last);
				restot = wxGetApp().AppDB.GetTotalNear(totdb,_T("<="));
				wxString sql = StrF(WXSQL_FOR_DATERANGE,
					first.Format(DATEFORM).c_str(),last.Format(DATEFORM).c_str(),handle);
				wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
				km_WeekDetail->SetColLabelValue(i+2,first.Format(DATEFORM));
				SetValueInDetail(&km_WeekDetail,i+2,rset,restot);
				first.Add(wxDateSpan(0,0,1,0));
				last.Add(wxDateSpan(0,0,1,0));
			}
		//monthly
		}else if (showtype == 2) {
			wxDateTime first = km_Calender->GetDate();
			first.SetDay(1);
			wxDateTime last = km_Calender->GetDate().GetLastMonthDay();
			first.Subtract(wxDateSpan(0,2,0,0));
			last.Subtract(wxDateSpan(0,2,0,0));

			for (int i = 0; i < 5; i++) {
				DB_total totdb, restot;
				totdb.SetHandling(handle);
				totdb.SetDate(last);
				restot = wxGetApp().AppDB.GetTotalNear(totdb,_T("<="));
				wxString sql = StrF(WXSQL_FOR_DATERANGE,
					first.Format(DATEFORM).c_str(),last.Format(DATEFORM).c_str(),handle);
				wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
				km_MonthDetail->SetColLabelValue(i+2,first.Format(_T("%Y/%m")));
				SetValueInDetail(&km_MonthDetail,i+2,rset,restot);
				first.Add(wxDateSpan(0,1,0,0));
				last.Add(wxDateSpan(0,1,0,0));
			}

		}
	}
	km_WeekDetail->Thaw();
	km_MonthDetail->Thaw();
}
//---------------------------------------------------------------
// set each total values in detail list
//---------------------------------------------------------------
void MyFrame::SetValueInDetail(wxGrid **grid, int gridcols, wxSQLite3ResultSet rset, DB_total &totdb)
{
	int rows = 0, cols = 0;
	int sumval = 0, sumin = 0, sumout = 0;
	const int CST_TOTALVALUE = 2;
	const int CST_IOFLAG = 3;
	wxColour colred(255,0,0), colblue(0,0,255);
	(*grid)->Freeze();
	//---total value of each expenses and items
	while (rset.NextRow()) {
		for (cols = CST_TOTALVALUE; cols < CST_IOFLAG; cols++) {
			//---set value
			(*grid)->SetCellValue(rows,gridcols,rset.GetString(cols));
			//---change color
			if (rset.GetInt(CST_IOFLAG) == 0) {
				(*grid)->SetCellTextColour(rows,gridcols,colblue);
				sumin += rset.GetInt(cols);
			}else{
				(*grid)->SetCellTextColour(rows,gridcols,colred);
				sumout += rset.GetInt(cols);
			}
			sumval += rset.GetInt(cols);
		}
		(*grid)->SetCellBackgroundColour(rows,4,wxColour(255,205,181));
		rows++;
	}
	rows++;
	/*(*grid)->SetCellValue(rows,gridcols,IntToStr(sumval));
	if ((sumin - sumout) != 0) {
		(*grid)->SetCellTextColour(rows,gridcols,((sumin - sumout) < 0) ? colred : colblue);
	}*/
	//---total income
	rows++;
	(*grid)->SetCellValue(rows,gridcols,IntToStr(sumin));
	if (sumin != 0) {
		(*grid)->SetCellTextColour(rows,gridcols,colblue);
	}
	//---total expenditure
	rows++;
	(*grid)->SetCellValue(rows,gridcols,IntToStr(sumout));
	if (sumout != 0) {
		(*grid)->SetCellTextColour(rows,gridcols,colred);
	}
	//---history of remainder
	rows++;
	(*grid)->SetCellValue(rows,gridcols,IntToStr(totdb.GetRemainder()));
	(*grid)->Thaw();
	grid = 0;
}
//---------------------------------------------------------------
// open kakeibo file
//---------------------------------------------------------------
void MyFrame::Open_File(const wxString name)
{
	if (!name.IsEmpty()) {
		wxGetApp().SetFilePath(name);
	}
	wxFileName fname(name);
	wxString newname = DecryptKakeibo(name);
	wxGetApp().SQLDB().Open(newname);
	wxGetApp().SQLDB().Begin();
	/*LOG*/wxGetApp().WriteLog(StrF(_("Opened %s."),name.c_str()));

	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ct_budget from db_counter;"));
	while (rset.NextRow()) wxGetApp().AppDB.CountBudget = rset.GetInt(0);
	rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ct_total from db_counter;"));
	while (rset.NextRow()) wxGetApp().AppDB.CountTotal = rset.GetInt(0);
	rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ct_expense from db_counter;"));
	while (rset.NextRow()) wxGetApp().AppDB.CountExpense = rset.GetInt(0);
	rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ct_items from db_counter;"));
	while (rset.NextRow()) wxGetApp().AppDB.CountItems = rset.GetInt(0);
	rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ct_account from db_counter;"));
	while (rset.NextRow()) wxGetApp().AppDB.CountAccount = rset.GetInt(0);

	wxGetApp().SetNewFlag(false);
	int tmpacc = 0;
	//---show default handling 
	rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ac_id from db_account;"));
	while (rset.NextRow()) {
		tmpacc = rset.GetInt(0);
		break;
	}
	//---get setting depends on each .kak file
	wxString sql = _T("select ac_initial from db_account where ac_id = %d;");
	wxGetApp().AppDB.AppSetting.SetRemainder(
		wxGetApp().SQLDB().ExecuteScalar(StrF(sql,tmpacc)));
	wxGetApp().AppDB.AppSetting.LoadDB();
	{//---Retrieve favorite transaction
		for (int i = 0; i < wxGetApp().AppDB.AppSetting.GetPeriodCount(); i++) {
			if (wxGetApp().AppDB.AppSetting.GetPeriod(i).GetTiming() == 3) {
				db_menufavorites.push_back(wxGetApp().AppDB.AppSetting.GetPeriod(i));
			}
		}
	}
	UpdateControl();
	//---processing periodical transaction
	int periodcnt = CheckSincePeriodical(wxDateTime::Now());
	/*LOG*/wxGetApp().WriteLog(StrF(_("Periodical transaction is %d at today."),periodcnt));
	if (periodcnt > 0) {
		//km_InfoPeriod->SetLabel(StrF(_("%d awaiting!"),periodcnt));
		km_TurnStackPeriod->SetLabel(StrF(_T("%s (%d)"),_("Awaiting"),periodcnt));
		km_StackPeriod->Clear();
		for (int i = 0; i < (int)stock_dbperiod.size(); i++) {
			wxString line = StrF(_T("%s %s.%s(%s)"),
				stock_dbperiod.at(i).GetBudget().GetDate().Format(DATEFORM).c_str(),
				wxGetApp().AppDB.GetExpense(stock_dbperiod.at(i).GetBudget().GetExpense(),stock_dbperiod.at(i).GetBudget().GetIO()).GetName().c_str(),
				wxGetApp().AppDB.GetItems(stock_dbperiod.at(i).GetBudget().GetItems(),stock_dbperiod.at(i).GetBudget().GetExpense()).GetName().c_str(),
				wxGetApp().AppDB.GetAccount(stock_dbperiod.at(i).GetBudget().GetHandling()).GetName().c_str());
			km_StackPeriod->Append(line);
		}
	}
	km_DayDetail->SetImageList(wxGetApp().icoList,wxIMAGE_LIST_SMALL);

	//---first page settings
	SetKakeiboTitle(fname,wxGetApp().AppDB.AppSetting.GetBookName());
	ChangePage(wxDateTime::Now(),tmpacc);
	GenerateExpenseInDetail(true,false,curhandling);
	SetExpense((InoutType)km_SerIO->GetSelection());
	km_SerExpense->SetSelection(0);
	SetItems(1);
	km_SerItems->SetSelection(0);
	turnControlState(true);

	//---add recent used file to the list
	RotateRecent(name);

}
//---------------------------------------------------------------
// save kakeibo file
//---------------------------------------------------------------
void MyFrame::Save_File(bool isoverwrite, const wxString &name)
{
	int key[5];
	if (wxGetApp().AppDB.AppSetting.GetEncrypt()) {
		wxString sql = _T("select * from db_counter;");
		wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
		while (rset.NextRow()) {
			for (int i = 0; i < WXSIZEOF(key); i++) {
				key[i] = rset.GetInt(i);
			}
		}
	}
	if (!isoverwrite) {
		wxFileDialog dialog(this,_("Please input file name for save."),_T(""),_T(""),
			_("Budget file (*.kak)|*.kak"),wxFD_SAVE|wxFD_OVERWRITE_PROMPT);
#ifdef __WIN64_DEBUG_ERROR_EVID
		wxString pp = wxGetTextFromUser(_T("input"),APPTITLE);
		if (!pp.IsEmpty()) {
			wxFileName fname(pp);
#else
		if (dialog.ShowModal() == wxID_OK) {
			wxFileName fname(dialog.GetPath());
#endif
			//---close kakeibo file once
			wxGetApp().SQLDB().Commit();
			wxGetApp().SQLDB().Close();
			//---complete file extension
			if (fname.GetExt().IsEmpty()) {
				fname.SetExt(_T("kak"));
			}

			if (wxGetApp().AppDB.AppSetting.GetEncrypt()) {
				wxString tempname = EncryptKakeibo(wxGetApp().GetFilePath(),key[0],key[1],key[2],key[3],key[4]);
				//---complete to save encrypted final kakeibo file to destination path.
				wxRenameFile(tempname,fname.GetFullPath(),true);
				wxGetApp().SQLDB().Open(wxGetApp().GetTempFilePath());
			}else{
				//---copy temporary file to destination path
				wxCopyFile(wxGetApp().GetFilePath(), fname.GetFullPath());
				//---if user save new file, remove temporary kakeibo file
				if (wxGetApp().IsNewFile()) {
					wxRemoveFile(wxGetApp().GetFilePath());
				}
				wxGetApp().SQLDB().Open(fname.GetFullPath());
			}

			wxGetApp().SetFilePath(fname.GetFullPath());
			wxGetApp().SQLDB().Begin();
			wxGetApp().SetNewFlag(false);
			//this->SetTitle(wxString::Format(_T("%s - %s"),dialog.GetFilename().c_str(),APPTITLE));
			SetKakeiboTitle(fname,wxGetApp().AppDB.AppSetting.GetBookName());
		}
	}else{
		wxGetApp().SQLDB().Commit();
		if (wxGetApp().AppDB.AppSetting.GetEncrypt()) {
			wxGetApp().SQLDB().Close();
			wxString tempname = EncryptKakeibo(wxGetApp().GetFilePath(),key[0],key[1],key[2],key[3],key[4]);
			wxRenameFile(tempname,wxGetApp().GetFilePath(),true);			wxGetApp().SQLDB().Open(wxGetApp().GetTempFilePath());
		}
		wxGetApp().SQLDB().Begin();
	}
	/*LOG*/wxGetApp().WriteLog(StrF(_("Saved %s."),name.c_str()));
	wxGetApp().SetChangeFlag(false);

}
//---------------------------------------------------------------
// update and refresh any controls on window
//---------------------------------------------------------------
void MyFrame::UpdateControl(void)
{
	dbaccountId.clear();
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(_T("select ac_id, ac_name from db_account;"));
	km_tool_Handling->Clear();
	km_SerHandling->Clear();
	//generate handling list
	while (rset.NextRow()) {
		dbaccountId.push_back(rset.GetInt(0));
		km_tool_Handling->Append(rset.GetString(1));
		km_SerHandling->Append(rset.GetString(1));
	}
	km_tool_Handling->SetSelection(0);
	km_SerHandling->SetSelection(0);
	curhandling = dbaccountId.at(km_tool_Handling->GetSelection());
	SetExpense(in_it);
	SetItems(1);
	for (size_t i = 0; i < db_menufavorites.GetCount(); i++) {
		SetFavoriteMenu(db_menufavorites.Item(i));
	}
}
//---------------------------------------------------------------
// close kakeibo file
//---------------------------------------------------------------
int MyFrame::Close_File(void)
{
	if (wxGetApp().SQLDB().IsOpen()) {
		if (wxGetApp().IsChanged()) {
			int ret = wxMessageBox(_("This file is changed.\nDo you save it before being closed?"),APPTITLE,
				wxYES_NO|wxCANCEL|wxICON_QUESTION,this);
			switch (ret) {
			case wxYES:
				if (wxGetApp().IsNewFile()) {
					Save_File(false);
				}else{
					Save_File(true);
				}
				wxGetApp().SQLDB().Commit();
				break;
			case wxNO:
				wxGetApp().SQLDB().Rollback();
				break;
			default:
				return -1;
			}
		}
		wxGetApp().SQLDB().Close();
		if (wxGetApp().IsNewFile()) {
			wxRemoveFile(wxGetApp().GetFilePath());
		}
		wxGetApp().AppDB.AppSetting.Clear(false);
		km_DayDetail->DeleteAllItems();
		km_WeekDetail->ClearGrid();
		km_MonthDetail->ClearGrid();
		km_tool_Handling->Clear();
		km_FinishPeriod->Clear();
		km_TurnFinishPeriod->SetLabel(_("Processed"));
		km_SearchDetail->DeleteAllItems();
		km_SerCondList->Clear();

		DB_total db;
		db.SetIncome(0);
		db.SetExpenditure(0);
		db.SetRemainder(0);
		ChangeRowTotal(db);
		turnControlState(false);
	}
	/*LOG*/wxGetApp().WriteLog(StrF(_("Closed %s."),wxGetApp().GetFilePath().c_str()));
	this->SetTitle(APPTITLE);
	return 0;
}
//---------------------------------------------------------------
// set preset expenses and items of expense
//---------------------------------------------------------------
void MyFrame::InsertPresetData(void)
{
	wxString langdir;
	wxLocale locale;
	locale.Init(wxLANGUAGE_DEFAULT);
	switch (locale.GetSystemLanguage()) {
	case wxLANGUAGE_JAPANESE:
		langdir = _T("ja");
		break;
	default:
		return;
	}
	langdir = locale.GetName().Left(2);
	//wxStandardPaths spath;
	wxString presetpath = _T("preset");
	wxFileName fullpath[2];
	fullpath[0].AssignDir(wxGetApp().GetStdPath().GetUserDataDir());
	fullpath[0].SetName(presetpath);
	fullpath[0].SetExt(langdir);
	fullpath[1].AssignDir(wxGetApp().GetStdPath().GetResourcesDir());
#ifdef __WXMSW__
	fullpath[1].AppendDir(wxGetApp().GetPathElement(P_SHARE));
	fullpath[1].AppendDir(wxGetApp().GetPathElement(P_APPNAME));
#endif
	fullpath[1].AppendDir(presetpath);
	//fullpath[1].AppendDir(langdir);
	fullpath[1].SetName(presetpath);
	fullpath[1].SetExt(langdir);
	wxTextFile tfile;
	bool openflag = false;
	//challenge to search preset file on multiple directories
	for (int i = 0; i < 2; i++) {
		openflag = tfile.Open(fullpath[i].GetFullPath());
		if (openflag) break;
	}
	if (!openflag) return;
	for (wxString str = tfile.GetFirstLine(); !tfile.Eof(); str = tfile.GetNextLine()) {
		if (!str.IsEmpty()) {
			wxGetApp().SQLDB().ExecuteUpdate(str);
		}
	}
	//---set accounts in items of expense
	int id[2], ix = 0;
	wxString sql = _T("select ex_id from db_expense where ex_account = '1' order by ex_id, ex_io;");
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
	while (rset.NextRow()) {
		id[ix] = rset.GetInt(0);
		ix++;
	}
	sql = _T("select ac_name from db_account order by ac_id");
	rset = wxGetApp().SQLDB().ExecuteQuery(sql);
	wxString accstr;
	while (rset.NextRow()) {
		accstr = rset.GetString(0);
	}
	for (ix = 0; ix < 2; ix++) {
		DB_items db;
		db.SetId(wxGetApp().AppDB.GetLastIdOfItems(id[ix]));
		db.SetImage(-1);
		db.SetExpense(id[ix]);
		db.SetName(accstr);
		wxGetApp().AppDB.AddItems(db);
	}

	tfile.Close();
}
//---------------------------------------------------------------
// check whether there is a target date in designated periods
//---------------------------------------------------------------
bool MyFrame::CheckBudgetDate(wxDateTime date, int handling, DB_reserved &db, int *result)
{
	bool resflag = false;
	wxDateTime st = db.GetStartDate();
	wxDateTime ed = db.GetEndDate();
	if (date.IsBetween(st,ed)) {
		int monthdiff = (int)date.GetMonth() - (int)st.GetMonth();
		wxDateTime settlest = st;
		wxDateTime settleed = date;
		settlest.Add(wxDateSpan(0,monthdiff,0,0));

		if (handling == db.GetHandling()) {
			settleed.Subtract(wxDateSpan(0,0,0,0));
			wxString sql = StrF(_T("select sum(tot_income) - sum(tot_expenditure) as sum_total from db_total where tot_handle = %d and tot_date between '%s' and '%s';"),
				handling, settlest.Format(DATEFORM).c_str(), settleed.Format(DATEFORM).c_str());
			*result = wxGetApp().SQLDB().ExecuteScalar(sql);
			resflag = true;
		}
	}
	return resflag;
}
//---------------------------------------------------------------
// check whether a target date was over the date of the designated period
//---------------------------------------------------------------
int MyFrame::CheckSincePeriodical(const wxDateTime &date)
{
	int cnt, result = 0, finregistcnt = 0;
	stock_dbperiod.clear();
	cnt = wxGetApp().AppDB.AppSetting.GetPeriodCount();
	if (cnt > 0) {
		for (int i = 0; i < cnt; i++) {
			DB_periodical db = wxGetApp().AppDB.AppSetting.GetPeriod(i);
			DB_day daydb;
			wxDateTime dbtime;
			//judge each timing
			switch (db.GetTiming()) {
			case 0://week
				{
					int wnum = date.GetWeekOfMonth();
					wxDateTime::WeekDay wk;
					if (wxGetApp().AppDB.AppSetting.GetStartWeekDay() == 0) {
						wk = (wxDateTime::WeekDay)(db.GetTimingDay() - 1);
					}else{
						wk = (wxDateTime::WeekDay)db.GetTimingDay();
						if (wk == wxDateTime::Inv_WeekDay) {
							wk = wxDateTime::Sun;
						}
					}
					dbtime = date;
					dbtime.SetToPrevWeekDay(wk);//,wnum,date.GetMonth(),date.GetYear());
				}
				break;
			case 1://month
				dbtime = date.GetLastMonthDay(date.GetMonth(),date.GetYear());
				if (dbtime.GetDay() >= db.GetTimingDay()) {
					dbtime.SetDay(db.GetTimingDay());
				}
				//Msgbox(dbtime.FormatDate(),this);
				break;
			case 2://last day
				dbtime = date.GetLastMonthDay(date.GetMonth(),date.GetYear());
				break;
			case 3://favorite transaction (ignore)
				continue;
			}
			if (dbtime.IsEarlierThan(db.GetDate())) continue;
			//when date passing
			//---destinated date is Saturday or Sunday or holiday
			wxDateTime cmpdate;
			cmpdate = dbtime;
			if (!wxGetApp().AppDB.IsWorkDayExtra(dbtime)) {
				switch (db.GetHoliday()) {
				case 1://before
					//cmpdate = dbtime;
					while (!wxGetApp().AppDB.IsWorkDayExtra(cmpdate)) {
						cmpdate.Subtract(wxDateSpan(0,0,0,1));
					}
					//daydb.SetDate(cmpdate);
					break;
				case 2://after
					//cmpdate = dbtime;
					while (!wxGetApp().AppDB.IsWorkDayExtra(cmpdate)) {
						cmpdate.Add(wxDateSpan(0,0,0,1));
					}
					//---check again, when date passing
					/*if (date.IsLaterThan(cmpdate)) {
						//daydb.SetDate(cmpdate);
					}else{
						continue;
					}*/
					break;
				default:
					//cmpdate = dbtime;
					break;
				}
			}
			//Msgbox(StrF(_T("db.GetDate()=%s\ncmpdate=%s\ndate=%s\n"),
			//	db.GetDate().FormatDate().c_str(),cmpdate.FormatDate().c_str(),date.FormatDate().c_str()),this);
			if (date.IsLaterThan(cmpdate)) {
				daydb = db.GetBudget();
				daydb.SetFlag(add_mt);
				//daydb.SetDate(dbtime);
				daydb.SetId(wxGetApp().AppDB.GetLastIdOfBudget(
					dbtime,(int)daydb.GetIO(),daydb.GetHandling()));
				daydb.SetExtra(daydb.GetExtra()+_T("pr:"));
				daydb.SetDate(cmpdate);
				//If it already registered, ignore this.
				if (!CheckAlreadyPeriodical(daydb,_T("pr"))) {
					//case of awaiting inputting
					if (db.GetInputValue() || db.GetInputMemo()) {
						result++;
						db.SetBudget(daydb);
						stock_dbperiod.push_back(db);
					}else{
					//case of possible to register
						finregistcnt++;
						wxString line = StrF(_T("%s %s.%s(%s)"),
							daydb.GetDate().Format(DATEFORM).c_str(),
							wxGetApp().AppDB.GetExpense(daydb.GetExpense(),daydb.GetIO()).GetName().c_str(),
							wxGetApp().AppDB.GetItems(daydb.GetItems(),daydb.GetExpense()).GetName().c_str(),
							wxGetApp().AppDB.GetAccount(daydb.GetHandling()).GetName().c_str());
						km_FinishPeriod->Append(line);
						dbbudget.push_back(daydb);
						UpdateLinkedBudget(daydb);
						UpdateDB();
					}
				}
			}
		}
	}
	if (finregistcnt > 0) {
		km_TurnFinishPeriod->SetLabel(StrF(_T("%s (%d)"),_("Processed"),finregistcnt));
	}
	return result;
}
//---------------------------------------------------------------
// check whether there is specified flag in destinated date
//---------------------------------------------------------------
bool MyFrame::CheckAlreadyPeriodical(DB_day &db, wxString flag)
{
	wxString sql = StrF(_T("select count(*) from db_budgets where bg_date = '%s' and bg_io = %d and bg_handle = %d and bg_expense = %d and bg_items = %d and bg_extra like '%s' and bg_memo = '%s';"),
		db.GetDate().Format(DATEFORM).c_str(),(int)db.GetIO(),db.GetHandling(),
		db.GetExpense(),db.GetItems(),StrF(_T("%%%s%%"),flag.c_str()).c_str(),
		db.GetMemo().c_str());
	return wxGetApp().SQLDB().ExecuteScalar(sql) > 0 ? true : false;
}
void MyFrame::SetExpense(InoutType io)
{
	wxString sql = _T("select ex_id, ex_image, ex_name from db_expense where ex_io = %d");
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(
		wxString::Format(sql,(int)io));
	km_SerExpense->Clear();
	dbexpenseId.clear();
	while (rset.NextRow()) {
		dbexpenseId.push_back(rset.GetInt(0));
		int i = rset.GetInt(1);
		if (i > -1) {
			km_SerExpense->Append(rset.GetString(2),wxGetApp().icoDList->GetBitmap(i));
		}else{
			km_SerExpense->Append(rset.GetString(2));
		}
	}
	km_SerExpense->SetSelection(0);
}
void MyFrame::SetItems(int expenseId)
{
	wxString sql = _T("select it_id, it_image, it_name from db_items where it_expense = %d");
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(
		wxString::Format(sql,expenseId));
	km_SerItems->Clear();
	dbitemsId.clear();
	while (rset.NextRow()) {
		dbitemsId.push_back(rset.GetInt(0));
		int i = rset.GetInt(1);
		if (i > -1) {
			km_SerItems->Append(rset.GetString(2),wxGetApp().icoDList->GetBitmap(i));
		}else{
			km_SerItems->Append(rset.GetString(2));
		}
	}
	km_SerItems->SetSelection(0);
}
//---------------------------------------------------------------
// generate linking transaction id
//---------------------------------------------------------------
wxString MyFrame::GenerateLinkId(const wxDateTime &date, int io, int handling, int id)
{
	int ye = date.GetYear() / 100;
	int ar = date.GetYear() % 100;
	int doy = date.GetDayOfYear();
	wxString hexx = StrF(_T("%X"),(ye+ar+doy)^io^handling^id);
	return hexx;
}
//---------------------------------------------------------------
// turn enable or disable control state
//---------------------------------------------------------------
void MyFrame::turnControlState(bool flag)
{
	//---turn "Save" to "Application log"
	for (int i = kakeibo_save; i < kakeibo_dellog+1; i++) {
		//---"exit" is exclude
		if (i != kakeibo_exit) {
			km_MenuBar->Enable(i,flag);
		}
	}
	km_ToolBar->EnableTool(kakeibo_save,flag);
	km_ToolBar->EnableTool(kakeibo_close,flag);
	km_ToolBar->EnableTool(kakeibo_adddetail,flag);
	km_ToolBar->EnableTool(kakeibo_moddetail,flag);
	km_ToolBar->EnableTool(kakeibo_deldetail,flag);
	km_tool_Handling->Enable(flag);

	km_JumpPast->Enable(flag);
	km_JumpFuture->Enable(flag);
	km_ClearPeriod->Enable(flag);

	mainPanel2->Enable(flag);
}
//---------------------------------------------------------------
// set kakeibo title on window title bar
//---------------------------------------------------------------
void MyFrame::SetKakeiboTitle(wxFileName &fname, const wxString &title)
{
	if (title.IsEmpty()) {
		this->SetTitle(wxString::Format(_T("%s - %s"),fname.GetFullName().c_str(),APPTITLE));
	}else{
		this->SetTitle(wxString::Format(_T("%s - %s"),title.c_str(),APPTITLE));
	}
	this->Refresh();

}
//---------------------------------------------------------------
// set favorate menu from DB_periodical
//---------------------------------------------------------------
void MyFrame::SetFavoriteMenu(DB_periodical &newrow)
{
	//---register menu bar
	wxMenuBar *menubar = GetMenuBar();
	wxMenu *menu = menubar->GetMenu(1);
	wxMenuItem *menuitem = menu->FindItem(kakeibo_favorite);
	wxMenu *cmenu = menuitem->GetSubMenu();
	//---===set expense name and item name of expense
	wxString labelname;
	int favcnt = 1;
	wxString sql = StrF(WXSQL_GET_EXPENSE_AND_ITEM,
		newrow.GetBudget().GetExpense(),newrow.GetBudget().GetItems());
	wxSQLite3ResultSet rset = wxGetApp().SQLDB().ExecuteQuery(sql);
	while (rset.NextRow()) {
		labelname = rset.GetString(0) + _T(" - ") +	rset.GetString(1) + _T(": ");
	}
	labelname += newrow.GetBudget().GetMemo();
	sql = StrF(WXSQL_GET_PERIOD_CNT_IF_TIMING,3);
	favcnt = wxGetApp().SQLDB().ExecuteScalar(sql);
	
	cmenu->Append(kakeibo_favzero+favcnt,labelname);

}
//---------------------------------------------------------------
// create sub-menu of recent file in the file menu
//---------------------------------------------------------------
void MyFrame::CreateRecent(void)
{
	//wxMenuBar *menubar = GetMenuBar();
	//wxMenu *menu = menubar->GetMenu(0);
	//wxMenuItem *menuitem = menu->FindItem(kakeibo_recentzero);
	//Msgbox(menuitem->GetLabel(),this);
	//wxMenu *recentmenu = new wxMenu();
	int startrecent = (int)kakeibo_recentzero;
	for (int i = 0; i < wxGetApp().AppDB.AppSetting.GetRecentCount(); i++) {
		km_file_recent->Append(++startrecent,StrF(_T("%d : %s"),(i+1),wxGetApp().AppDB.AppSetting.GetRecent(i).c_str()));
	}
	//menuitem->SetSubMenu(recentmenu);
	//menu->AppendSubMenu(recentmenu,_("Recent used file"));
	
}
//---------------------------------------------------------------
// rotate recent file array after to add new opening file
//---------------------------------------------------------------
void MyFrame::RotateRecent(const wxString &newfile)
{
	//---If last opend file and now opening file is equal, do not add recent list
	if (wxGetApp().AppDB.AppSetting.GetRecentCount() > 0) {
		if (wxGetApp().AppDB.AppSetting.GetRecent(wxGetApp().AppDB.AppSetting.GetRecentCount()-1) == newfile) {
			return;
		}
	}
	wxGetApp().AppDB.AppSetting.PushRecent(newfile,true);
	//regenerate menu string
	//---register menu bar
	//wxMenuBar *menubar = GetMenuBar();
	//wxMenu *menu = menubar->GetMenu(0);
	//wxMenuItem *menuitem = menu->FindItem(kakeibo_recentzero);
	//wxMenu *recentmenu = menuitem->GetSubMenu();
	int startrecent = (int)kakeibo_recentzero;
	for (int i = 0; i < wxGetApp().AppDB.AppSetting.GetRecentCount(); i++) {
		startrecent++;
		if ((int)km_file_recent->GetMenuItemCount() > (startrecent-kakeibo_recentzero)) {
			km_file_recent->SetLabel(startrecent,StrF(_T("%d : %s"),(i+1),wxGetApp().AppDB.AppSetting.GetRecent(i).c_str()));
		}else{
			km_file_recent->Append(startrecent,StrF(_T("%d : %s"),(i+1),wxGetApp().AppDB.AppSetting.GetRecent(i).c_str()));
		}
	}
}
void MyFrame::GetReportHeaderInfo(bool *enable, bool *useline, wxString header[])
{
	*enable = km_ReportEnableHeader->GetValue();
	*useline = km_ReportLineHeader->GetValue();
	for (int i = 0; i < WXSIZEOF(km_ReportHeader); i++) header[i] = km_ReportHeader[i]->GetValue();
}
void MyFrame::GetReportFooterInfo(bool *enable, bool *useline, wxString footer[])
{
	*enable = km_ReportEnableFooter->GetValue();
	*useline = km_ReportLineFooter->GetValue();
	for (int i = 0; i < WXSIZEOF(km_ReportFooter); i++) footer[i] = km_ReportFooter[i]->GetValue();

}
void MyFrame::SetReportHeaderInfo(bool enable, bool useline, wxString header[])
{
	km_ReportEnableHeader->SetValue(enable);
	km_ReportLineHeader->SetValue(useline);
	for (int i = 0; i < WXSIZEOF(km_ReportHeader); i++) km_ReportHeader[i]->SetValue(header[i]);
}
void MyFrame::SetReportFooterInfo(bool enable, bool useline, wxString footer[])
{
	km_ReportEnableFooter->SetValue(enable);
	km_ReportLineFooter->SetValue(useline);
	for (int i = 0; i < WXSIZEOF(km_ReportFooter); i++) km_ReportFooter[i]->SetValue(footer[i]);
}
int MyFrame::GetReportOptions(bool options[])
{
	for (size_t i = 0; i < km_ReportOptions->GetCount(); i++) {
		options[i] = km_ReportOptions->IsChecked(i);
	}
	return (int)km_ReportOptions->GetCount();
}
void MyFrame::SetReportOptions(bool options[])
{
	for (size_t i = 0; i < km_ReportOptions->GetCount(); i++) {
		km_ReportOptions->Check(i, options[i]);
	}
}